package org.vsg.security.model.service.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import org.vsg.common.biz.exception.ServiceException;
import org.vsg.common.pagination.Pagination;
import org.vsg.common.pagination.PaginationException;
import org.vsg.common.pagination.carrier.Carrier;
import org.vsg.common.pagination.carrier.HttpSingleSortRecordLimitCarrier;
import org.vsg.common.pagination.carrier.RecordLimitCarrier;
import org.vsg.common.pagination.datatrans.PaginationProvider;
import org.vsg.common.pagination.datatrans.PaginationProviderFactory;
import org.vsg.security.model.domain.SysRole;
import org.vsg.security.model.persistence.SysRoleDao;
import org.vsg.security.model.service.SysRoleService;


public class SysRoleServiceImpl implements SysRoleService {
	/**
	 * set the pagination provider factory
	 * 
	 * 
	 */
	private PaginationProviderFactory factory = PaginationProviderFactory
			.getInstance();

	private SysRoleDao sysRoleDao;

	/**
	 * @param carrier
	 * @return
	 * @exception ServiceException
	 * @exception PaginationException
	 */
	public Pagination pageSysRole(Carrier carrier) throws ServiceException,
			PaginationException {
		// TODO: implement
		PaginationProvider provider = factory
				.generateProvider((RecordLimitCarrier) carrier);
		return sysRoleDao.pageSysRole(provider);
	}

	/**
	 * @param carrier
	 * @return
	 * @throws ServiceException
	 * @exception PaginationException
	 */
	public Pagination pageSysRoleByAll(Carrier carrier) throws ServiceException,
			PaginationException {
		// TODO: implement
		PaginationProvider provider = factory
				.generateProvider((RecordLimitCarrier) carrier);
		return sysRoleDao.pageSysRoleByAll(provider);
	}
	
	@Override
	public void saveAll(Collection<SysRole> all)
			throws ServiceException {
		// TODO Auto-generated method stub
		sysRoleDao.saveAll(all);
		
	}  	

	/**
	 * @param sysRole
	 * @exception ServiceException
	 */
	public void addSysRole(SysRole sysRole) throws ServiceException {
		// TODO: implement
		sysRoleDao.save(sysRole);
	}

	/**
	 * @param sysRole
	 * @exception ServiceException
	 */
	public void updateSysRole(SysRole sysRole) throws ServiceException {
		// TODO: implement
		sysRoleDao.update(sysRole);
	}

	/**
	 * @param sysRole
	 * @exception ServiceException
	 */
	public void updateSimpleSysRole(SysRole newEntity) throws ServiceException {
		// TODO: implement
		SysRole original = sysRoleDao.load( newEntity.getId() );
		
		original.setId( newEntity.getId()  );
		original.setFlagInactive( newEntity.getFlagInactive()  );
		original.setCode( newEntity.getCode()  );
		original.setName( newEntity.getName() );
		original.setDescription( original.getDescription() );
		
		// --- update the method ---
		sysRoleDao.update( original );		
		
	}

	/**
	 * @param sysRole
	 * @exception ServiceException
	 */
	public void deleteSysRole(SysRole sysRole) throws ServiceException {
		// TODO: implement
		sysRoleDao.delete(sysRole);
	}

	@Override
	public void deleteAll(Collection<SysRole> all)
			throws ServiceException {
		// TODO Auto-generated method stub
		sysRoleDao.deleteAll(all);
	}
	
	@Override
	public void markDeleteSysRole(SysRole sysRole) throws ServiceException {
		// TODO Auto-generated method stub
		SysRole loadSysRole = sysRoleDao.load( sysRole.getId() );
		loadSysRole.setFlagDeleted( (short)1 );
		sysRoleDao.update( loadSysRole );
	}	
	
	
	@Override
	public Pagination pageAvailableHierarchyRoles(Carrier carrier)
			throws ServiceException, PaginationException {
		// TODO Auto-generated method stub
		HttpSingleSortRecordLimitCarrier limitCarrier = (HttpSingleSortRecordLimitCarrier)carrier;
		String roleId = (String)limitCarrier.getParameter("roleId");

		Set<SysRole> hierarchyRoles = new HashSet<SysRole>();
		
		// ---- get the hierarchy roles --- 
		if (roleId != null) {
			
			SysRole role = sysRoleDao.load( Integer.parseInt(roleId) );
			
			hierarchyRoles.add( role );
			
			hierarchyRoles.addAll( role.getDependenceRoles() );
			
			lookupAllHierarchyRoleByRole(role , hierarchyRoles);
			
		}
		
		limitCarrier.setParameterObject("existRoles", (HashSet)hierarchyRoles);
		
		PaginationProvider provider = factory.generateProvider(limitCarrier);
		
		Pagination page = this.sysRoleDao.pageAvailableHierarchyRoles(provider);
		
		return page;
	}

	
	
	@Override
	public Pagination pageAvailableConflictRole(Carrier carrier)
			throws ServiceException, PaginationException {
		// TODO Auto-generated method stub
		HttpSingleSortRecordLimitCarrier limitCarrier = (HttpSingleSortRecordLimitCarrier)carrier;
		String roleId = (String)limitCarrier.getParameter("roleId");

		Set<SysRole> conflictRoles = new HashSet<SysRole>();
		
		// ---- get the hierarchy roles --- 
		if (roleId != null) {
			
			SysRole role = this.sysRoleDao.load( new Integer(roleId) );

			conflictRoles.add( role );
			conflictRoles.addAll( role.getConflictRoles() );
		}
		
		limitCarrier.setParameterObject("conflictRole", (HashSet)conflictRoles);		
		
		PaginationProvider provider = factory.generateProvider((RecordLimitCarrier)carrier);
		Pagination page = this.sysRoleDao.pageAvailableConflictRole(provider);
		return page;
	}
	
	

	@Override
	public Pagination pageUndefinedHierarchyRoles(Carrier carrier)
			throws ServiceException, PaginationException {
		// TODO Auto-generated method stub
		PaginationProvider provider = factory.generateProvider((RecordLimitCarrier)carrier);
		Pagination page = this.sysRoleDao.pageUndefinedHierarchyRoles(provider);
		return page;

		
	}
	
	@Override
	public Pagination pageAvailableHierarchyRolesForOne(Carrier carrier)
			throws ServiceException, PaginationException {
		// TODO Auto-generated method stub
		HttpSingleSortRecordLimitCarrier limitCarrier = (HttpSingleSortRecordLimitCarrier)carrier;
		String roleId = (String)limitCarrier.getParameter("roleId");

		Set<SysRole> hierarchyRoles = new HashSet<SysRole>();
		
		// ---- get the hierarchy roles --- 
		if (roleId != null) {
			
			SysRole role = new SysRole();
			role.setId( Integer.parseInt(roleId) );

			hierarchyRoles.add( role );
			
			lookupAllHierarchyRoleByRole(role , hierarchyRoles);
			
		}
		
		limitCarrier.setParameterObject("existRoles", (HashSet)hierarchyRoles);
		
		PaginationProvider provider = factory.generateProvider(limitCarrier);
		
		Pagination page = this.sysRoleDao.pageAvailableHierarchyRoles(provider);		
		
		return page;
	}
	

	@Override
	public Pagination pageSysRoleHierarchy(Carrier carrier)
			throws ServiceException, PaginationException {
		// TODO Auto-generated method stub
		PaginationProvider provider = factory.generateProvider((RecordLimitCarrier) carrier);
		return sysRoleDao.pageSysRoleHierarchy(provider);
	}

	@Override
	public void removeRoles(int[] ids) throws ServiceException {
		// TODO Auto-generated method stub
		Collection<SysRole> roles = new Vector<SysRole>();
		SysRole role = null;
		for (int i = 0 ; i < ids.length ; i++) {
			role =  sysRoleDao.load( ids[i]);
			role.setFlagDeleted( (short)1 );
			roles.add( role );
		}
		this.sysRoleDao.saveAll( roles );
	}
	
	/**
	 * @param pk
	 * @exception ServiceException
	 */
	public SysRole loadSysRole(Serializable pk) throws ServiceException {
		// TODO: implement
		return sysRoleDao.load(pk);
	}

	@Override
	public SysRole getByCode(String code) throws ServiceException {
		// TODO Auto-generated method stub
		Collection<SysRole> some = sysRoleDao.findByCode(code);
		SysRole sysRole = null;
		Iterator<SysRole> itera = some.iterator();
		if ( itera.hasNext() ) {
			sysRole = itera.next();
		}
		return sysRole;
	}

	
	
	
	@Override
	public Collection<SysRole> findByAll() throws ServiceException {
		// TODO Auto-generated method stub
		return sysRoleDao.findByAll();
	}


	public SysRoleDao getSysRoleDao() {
		return sysRoleDao;
	}

	/**
	 * @param newSysRoleDao
	 */
	public void setSysRoleDao(SysRoleDao newSysRoleDao) {
		sysRoleDao = newSysRoleDao;
	}

	@Override
	public void updateRoleHierarchy(SysRole mainRole, String[] beLongRoles)
			throws ServiceException {
		// TODO Auto-generated method stub
		SysRole owner = sysRoleDao.load( mainRole.getId() );
		
		Set<SysRole> depeRoles = owner.getDependenceRoles();
		depeRoles.clear();

		
		SysRole newDepeRole = null;
		for (String depRoleId : beLongRoles) {
			if (!depRoleId.equals("")) {
				newDepeRole = sysRoleDao.load( new Integer(depRoleId) );
				depeRoles.add( newDepeRole );
			}
		}
		
		sysRoleDao.update( owner );

	}


	@Override
	public Pagination pageAvailableRolesOfUser(Carrier carrier)	throws ServiceException, PaginationException {
		// TODO Auto-generated method stub
		PaginationProvider provider = factory.generateProvider((RecordLimitCarrier) carrier);
		return sysRoleDao.pageAvailableRolesOfUser(provider);
	}

	@Override
	public void removeRoleConflict(SysRole mainRole, String[] roleIds)
			throws ServiceException {
		// TODO Auto-generated method stub
		SysRole owner = sysRoleDao.load( mainRole.getId() );
		
		Set<SysRole> conflictRoles = owner.getConflictRoles();
		
		Set<SysRole> removedRoles = new HashSet<SysRole>();
		
		SysRole conflictRole = null;
		
		for (int i = 0 ; i < roleIds.length ; i++) {
			
			Iterator<SysRole> ownerRoleItera = conflictRoles.iterator();
			while ( ownerRoleItera.hasNext() ) {
				conflictRole = ownerRoleItera.next();
				if (conflictRole.getId() == Integer.parseInt( roleIds[i] )) {
					removedRoles.add( conflictRole  );
					ownerRoleItera.remove();
				}
			}
		}
		
		
		
		// --- update another conflict role first ---
		Set<SysRole> otherConflictRoles = null;
		for (Iterator<SysRole> removeRoleIter = removedRoles.iterator() ; removeRoleIter.hasNext() ; ) {
			conflictRole = removeRoleIter.next();
			otherConflictRoles = conflictRole.getConflictRoles();
			otherConflictRoles.remove( owner );
			
			sysRoleDao.update( conflictRole );
		}
		
		sysRoleDao.update( owner );		
	}

	@Override
	public void addRoleConflict(SysRole mainRole, String[] roleIds)
			throws ServiceException {
		// TODO Auto-generated method stub
		SysRole owner = sysRoleDao.load( mainRole.getId() );
		
		Set<SysRole> conflictRoles = owner.getConflictRoles();
		
		SysRole conflictRole = null;
		
		for (int i = 0 ; i < roleIds.length ; i++) {
			conflictRole = sysRoleDao.load( new Integer(roleIds[i]) );
			conflictRoles.add( conflictRole );
		}
		
		// --- update another conflict role first ---
		Set<SysRole> otherConflictRoles = null;
		for (Iterator<SysRole> confRoleIter = conflictRoles.iterator() ; confRoleIter.hasNext() ; ) {
			conflictRole = confRoleIter.next();
			otherConflictRoles = conflictRole.getConflictRoles();
			if (! otherConflictRoles.contains(owner) )  {
				otherConflictRoles.add( owner );
				// --- update other role ----
				sysRoleDao.update( conflictRole );
			}
		}
		
		sysRoleDao.update( owner );
		
	}

	private void lookupAllHierarchyRoleByRole(SysRole role , Set<SysRole> container) {
		Collection<SysRole> roleList = this.sysRoleDao.findParentsByRole( role );
		for (SysRole hierarchyRole : roleList) {
			// --- add container ---
			container.add( hierarchyRole );
			lookupAllHierarchyRoleByRole( hierarchyRole , container );
			
		}		
	}

}